package myJsonMarshal

import (
	"errors"
	"fmt"
	"reflect"
)

//JsonMarshal 输入结构体数据，返回json字符流和error
func JsonMarshal(v interface{}) ([]byte, error) {
	b, err := Marshal(v)
	if err != nil {
		return nil, err
	}
	return b, nil
}

//Marshal 将接口数据类型的数据转为json字符流
func Marshal(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	typeJson := json.Type()

	switch typeJson.Kind() {
	case reflect.Invalid:
		return []byte("Invalid"), errors.New("Invalid")

	case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
		reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
		reflect.Uint64, reflect.Float32, reflect.Float64:
		return []byte(fmt.Sprintf("%v", json.Interface())), nil

	case reflect.String:
		return StringTrans(v)

	case reflect.Struct:
		return StructTrans(v)

	case reflect.Map:
		return MapTrans(v)

	case reflect.Slice:
		return SliceTrans(v)

	case reflect.Array:
		return ArrayTrans(v)

	case reflect.Ptr:
		return PtrTrans(v)

	default:
		return []byte("unsupportedTypeTrans"), errors.New("unsupportedTypeTrans")
	}
}

//StringTrans 将string数据转为json字符流
func StringTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	return []byte("\"" + json.String() + "\""), nil
}

//StructTrans 将struct数据转为json字符流
func StructTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	typeJson := json.Type()
	b := "{"

	for i := 0; i < json.NumField(); i++ {

		if i > 0 {
			b = b + ","
		}

		tag := typeJson.Field(i).Tag.Get("mytag")
		if tag == "" {
			b = b + "\"" + typeJson.Field(i).Name + "\":"
		} else {
			b = b + "\"" + tag + "\":"
		}

		tmp, err := Marshal(json.Field(i).Interface())
		if err != nil {
			return nil, err
		}
		b = b + string(tmp)
	}

	b = b + "}"

	return []byte(b), nil
}

//MapTrans 将map数据转为json字符流
func MapTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	i := json.MapRange()
	first := true
	b := "{"

	for i.Next() {
		if first {
			first = false
		} else {
			b = b + ","
		}

		b = b + "\"" + fmt.Sprintf("\"%v\":", i.Key()) + "\":"

		tmp, err := Marshal(i.Value().Interface())
		if err != nil {
			return nil, err
		}
		b = b + string(tmp)
	}

	b = b + "}"

	return []byte(b), nil
}

//SliceTrans 将slice数据转为json字符流
func SliceTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	b := "["

	for i := 0; i < json.Len(); i++ {
		if i > 0 {
			b = b + ","
		}

		tmp, err := Marshal(json.Index(i).Interface())
		if err != nil {
			return nil, err
		}

		b = b + string(tmp)
	}

	b = b + "]"
	return []byte(b), nil
}

//ArrayTrans 将array数据转为json字符流
func ArrayTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	b := "["

	for i := 0; i < json.Len(); i++ {
		if i > 0 {
			b = b + ","
		}

		tmp, err := Marshal(json.Index(i).Interface())
		if err != nil {
			return nil, err
		}

		b = b + string(tmp)
	}

	b = b + "]"
	return []byte(b), nil
}

//PtrTrans 将ptr数据转为json字符流
func PtrTrans(v interface{}) ([]byte, error) {
	json := reflect.ValueOf(v)
	return Marshal(json.Elem().Interface())
}

/*
type Stu struct {
	Name  string `mytag:"name"`
	Age   int
	HIgh  bool
	Class *Class `mytag:"class"`
}

type Class struct {
	Name  string
	Grade int
}

func main() {
	//实例化一个数据结构，用于生成json字符串
	stu := Stu{
		Name: "张三",
		Age:  18,
		HIgh: true,
	}

	//指针变量
	cla := new(Class)
	cla.Name = "1班"
	cla.Grade = 3
	stu.Class = cla

	//Marshal失败时err!=nil
	jsonStu, err := JsonMarshal(stu)
	if err != nil {
		fmt.Println("生成json字符串错误")
	}

	//jsonStu是[]byte类型，转化成string类型便于查看
	fmt.Println(string(jsonStu))
}
*/
